#ifndef MULTIPLECAPACITY_H_
#define MULTIPLECAPACITY_H_

#include "graph_support/GraphSupport.h"

#include "graph_support/attributes/FlowEdgeAttributes.h"

namespace GRAPH_SUPPORT_NS
{
namespace utils
{
namespace test_my_graph
{

/**
 * contains Cnt indicators of flow
 */
template< int Cnt >
class MultipleCapacity : public attributes::FlowEdgeAttributes::Capacity
{
private:
	typedef MultipleCapacity< Cnt > MyT;
	typedef MultipleCapacity< Cnt - 1 > MinorT;

	static std::vector< int > tail( const std::vector< int > & v )
	{
		assert( v.size() > 0 );
		std::vector< int > vc( v.size() - 1 );
		std::vector< int >::const_iterator it = v.begin();
		++it;
		std::copy( it, v.end(), vc.begin() );
		return vc;
	}

public:
	MultipleCapacity( int value = 0 )
		: value( value )
		, minorFlow( 0 )
	{
	}

	MultipleCapacity( const std::vector< int > & values )
		: value( values[0] )
		, minorFlow( tail( values ) )
	{
	}

	MultipleCapacity( int value, const MinorT & minotFlow )
		: value( value )
		, minorFlow( minotFlow )
	{
	}

	const MultipleCapacity & operator = ( int value )
	{
		this->value = value;
		minorFlow = 0;
		return * this;
	}

public:
	bool operator < ( const MyT & that ) const
	{
		return value < that.value ? true : ( minorFlow < that.minorFlow );
	}

	bool operator <= ( const MyT & that ) const
	{
		return value < that.value ? true : ( minorFlow <= that.minorFlow );
	}

	bool operator > ( const MyT & that ) const
	{
		return value > that.value ? true : ( minorFlow > that.minorFlow );
	}

	bool operator >= ( const MyT & that ) const
	{
		return value > that.value ? true : ( minorFlow >= that.minorFlow );
	}

	bool operator == ( const MyT & that ) const
	{
		return value == that.value && ( minorFlow == that.minorFlow );
	}

public:
	MyT operator + ( const MyT & that ) const
	{
		return MyT( value + that.value, minorFlow + that.minorFlow );
	}

	MyT operator - ( const MyT & that ) const
	{
		return MyT( value - that.value, minorFlow - that.minorFlow );
	}

	MyT operator += ( const MyT & that )
	{
		value += that.value;
		minorFlow += that.minorFlow;
		return *this;
	}

	MyT operator -= ( const MyT & that )
	{
		value -= that.value;
		minorFlow -= that.minorFlow;
		return *this;
	}

public:
	std::string toString() const
	{
		return std::string( "MF" ) + boost::lexical_cast< std::string >( Cnt ) + "<" + toStringInternal() + ">";
	}

	std::string toStringInternal() const
	{
		return boost::lexical_cast< std::string >( value ) + ( Cnt > 1 ? ", " : "" ) + minorFlow.toStringInternal();
	}

private:
	int value;
	MinorT minorFlow;
};

/**
 * STOP CHAIN CLASS
 */
template< >
class MultipleCapacity< 0 > : public attributes::FlowEdgeAttributes::Capacity
{
private:
	typedef MultipleCapacity< 0 > MyT;

public:
	MultipleCapacity( int value = 0 )
	{
		assert( value == 0 );
	}

	MultipleCapacity( const std::vector< int > & values )
	{
		assert( values.empty() );
	}

	const MyT & operator = ( int value )
	{
		assert( value == 0 );
		return * this;
	}

public:
	bool operator < ( const MyT & ) const
	{
		return false;
	}

	bool operator <= ( const MyT & ) const
	{
		return true;
	}

	bool operator > ( const MyT & ) const
	{
		return false;
	}

	bool operator >= ( const MyT & ) const
	{
		return true;
	}

	bool operator == ( const MyT & ) const
	{
		return true;
	}

public:
	const MyT & operator + ( const MyT & ) const
	{
		return *this;
	}

	const MyT & operator - ( const MyT & ) const
	{
		return *this;
	}

	const MyT & operator += ( const MyT & ) const
	{
		return *this;
	}

	const MyT & operator -= ( const MyT & ) const
	{
		return *this;
	}

public:
	std::string toString() const
	{
		return toStringInternal();
	}

	std::string toStringInternal() const
	{
		return "/";
	}
};

template< int Cnt >
std::ostream & operator << ( std::ostream & str, const MultipleCapacity< Cnt > & mc )
{
	str << mc.toString();
	return str;
}

}
}
}

#endif /* MULTIPLECAPACITY_H_ */
